package com.git.hui.yinshua.biz.order.service;

import com.git.hui.yinshua.api.model.order.OrderStatusEnum;
import com.git.hui.yinshua.api.model.order.PtOrderStatusEnum;
import com.git.hui.yinshua.biz.order.dao.entity.OrderEntity;
import com.git.hui.yinshua.biz.order.dao.entity.PtOrderEntity;
import com.git.hui.yinshua.biz.order.dao.entity.PtOrderItemEntity;
import com.git.hui.yinshua.biz.order.dao.repository.OrderRepository;
import com.git.hui.yinshua.biz.order.dao.repository.PtOrderRepository;
import com.git.hui.yinshua.biz.order.service.convert.OrderConvert;
import com.git.hui.yinshua.biz.pay.service.RefundService;
import com.git.hui.yinshua.biz.rest.models.order.req.PtOrderQueryReq;
import com.git.hui.yinshua.biz.rest.models.order.rsp.PtOrderDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 拼团服务
 *
 * @author YiHui
 * @date 2024/7/2
 */
@Slf4j
@Service
public class PtOrderService {
    @Autowired
    private PtOrderRepository ptOrderRepository;
    @Autowired
    private RefundService refundService;
    @Autowired
    private OrderRepository orderRepository;

    /**
     * 关闭拼团单
     *
     * @param ptOrderId
     */
    @Transactional(rollbackFor = Exception.class)
    public void autoClosePtOrder(Integer ptOrderId) {
        // 标记拼团失败
        PtOrderEntity order = ptOrderRepository.queryPtOrderForLock(ptOrderId);
        if (ptNumOver(order)) {
            // 如果这个时候拼团人数正好够了，那么不关单
            return;
        }

        // 拼团订单失败
        ptOrderRepository.updateAllPtOrderStatus(ptOrderId, PtOrderStatusEnum.FAILED.getStatus());
        // 拼团下的关联订单，需要自动发起退款
        // fixme --> 注意事务一致性问题
        order.getItemList().forEach(item -> {
            if (item.getPtStatus().equals(PtOrderStatusEnum.SUCCEED.getStatus())) {
                refundService.refunding(item.getRelatedOrderId(), "拼团失败，自动退款");
            }
        });
    }

    /**
     * 校验拼团订单是否完成，若完成，则将订单状态未更新的，自动更新为待打印
     *
     * @param ptOrderId 拼团订单
     */
    public boolean autoCheckPtOrder(Integer ptOrderId) {
        PtOrderEntity order = ptOrderRepository.queryPtOrderForLock(ptOrderId);
        if (!ptSucceedNum(order)) {
            // 拼团成功，更新拼团中的各个订单状态
            return false;
        }

        if (!Objects.equals(order.getPtStatus(), PtOrderStatusEnum.SUCCEED.getStatus())) {
            // 更新拼团单状态
            ptOrderRepository.updatePtOrderStatus(ptOrderId, PtOrderStatusEnum.SUCCEED.getStatus());
        }

        order.getItemList().forEach(item -> {
            if (Objects.equals(item.getPtStatus(), PtOrderStatusEnum.SUCCEED.getStatus())) {
                // 拼团成功，更新对应的订单状态
                OrderEntity o = orderRepository.querySimpleOrderForUpdate(item.getRelatedOrderId());
                if (o.getOrderStatus().equals(OrderStatusEnum.PT_ING.getStatus())) {
                    orderRepository.updateOrderStatus(item.getRelatedOrderId(), OrderStatusEnum.TO_PRINT.getStatus());
                }
            }
        });
        return true;
    }

    /**
     * 用户订单支付成功，更新对应的拼团单状态
     *
     * @param orderId
     * @response true 拼团单完成  false 表示拼团单没有成功
     */
    public boolean ptOrderItemPaySucceed(Long orderId) {
        PtOrderEntity ptOrder = doQueryPtOrderByOrderId(orderId);
        if (ptOrder == null) {
            // 根据订单，找不到对应的拼团单，则不执行后续的流程
            return false;
        }

        // 记录拼团单中已支付的成员数量
        int activeNum = 0;
        PtOrderItemEntity currentItem = null;
        for (PtOrderItemEntity item : ptOrder.getItemList()) {
            if (item.getRelatedOrderId().equals(orderId)) {
                currentItem = item;
            } else if (PtOrderStatusEnum.SUCCEED.getStatus().equals(item.getPtStatus())) {
                activeNum += 1;
            }
        }
        if (activeNum == ptOrder.getPtNum() - 1) {
            // 1. 拼团成功
            ptOrderRepository.updateAllPtOrderStatus(ptOrder.getId(), PtOrderStatusEnum.SUCCEED.getStatus());
            return true;
        }

        // 如果当前订单为团长，则将拼团订单状态设置为 进行中
        if (Objects.equals(currentItem.getUid(), ptOrder.getUid())) {
            // 2. 团长，支付成功，则表示开团成功
            ptOrderRepository.updatePtItemStatus(orderId, PtOrderStatusEnum.SUCCEED.getStatus());
            ptOrderRepository.updatePtOrderStatus(ptOrder.getId(), PtOrderStatusEnum.ING.getStatus());
            return false;
        }

        // 3. 如果当前订单为中间的订单，则拼团订单不做任何处理
        ptOrderRepository.updatePtItemStatus(orderId, PtOrderStatusEnum.SUCCEED.getStatus());
        return false;
    }

    /**
     * 拼团成员订单超时未支付自动取消
     *
     * @param orderId
     */
    public void ptOrderItemCanceled(Long orderId) {
        PtOrderEntity ptOrder = doQueryPtOrderByOrderId(orderId);
        if (ptOrder == null) {
            // 根据订单，找不到对应的拼团单，则不执行后续的流程
            return;
        }

        // 找到当前这个拼团单明细，将状态标记为失败
        PtOrderItemEntity item = ptOrder.getItemList().stream().filter(s -> s.getRelatedOrderId().equals(orderId)).findFirst().get();
        item.setPtStatus(PtOrderStatusEnum.FAILED.getStatus());

        // 如果所有拼团订单都是失败
        if (ptOrder.getItemList().stream().allMatch(s -> Objects.equals(s.getPtStatus(), PtOrderStatusEnum.FAILED.getStatus())
                || Objects.equals(s.getPtStatus(), PtOrderStatusEnum.CANCELED.getStatus()))) {
            ptOrderRepository.updateAllPtOrderStatus(ptOrder.getId(), PtOrderStatusEnum.FAILED.getStatus());
        } else {
            // 非团长，标记自己为失败即可
            ptOrderRepository.updatePtItemStatus(orderId, PtOrderStatusEnum.FAILED.getStatus());
        }
    }

    /**
     * 判断拼团是否满员
     *
     * @param ptOrder
     * @return
     */
    public boolean ptNumOver(PtOrderEntity ptOrder) {
        // 2. 判断是否可以成团：
        // 成团人数要求
        int ptNum = ptOrder.getPtNum();
        // 当前参团人数
        int activeNum = (int) ptOrder.getItemList().stream().filter(s -> !Objects.equals(s.getPtStatus(), PtOrderStatusEnum.CANCELED.getStatus())
                && !Objects.equals(s.getPtStatus(), PtOrderStatusEnum.FAILED.getStatus())).count();
        return activeNum >= ptNum;
    }

    /**
     * 判断拼团是否成功
     *
     * @param ptOrder 拼团单
     * @return true 表示拼团成功，所有的订单都完成支付
     */
    public boolean ptSucceedNum(PtOrderEntity ptOrder) {
        int ptNum = ptOrder.getPtNum();
        int succeedNum = (int) ptOrder.getItemList().stream().filter(s -> s.getPtStatus().equals(PtOrderStatusEnum.SUCCEED.getStatus())).count();
        return succeedNum >= ptNum;
    }


    /**
     * 查询商品的正在进行的拼团列表
     *
     * @param goodsId
     * @return
     */
    public List<PtOrderDto> queryPtOrderListByGoodsId(Integer goodsId) {
        PtOrderQueryReq req = new PtOrderQueryReq();
        req.setGoodsId(goodsId);
        req.autoInitReq();
        // 只查进行中的拼团单
        req.setState(Arrays.asList(PtOrderStatusEnum.ING.getStatus()));

        List<PtOrderEntity> list = ptOrderRepository.listOrder(req);
        return OrderConvert.batchToPtOrders(list);
    }

    /**
     * 根据订单批量查询拼团列表
     *
     * @param orderIds
     * @return
     */
    public List<PtOrderDto> queryPtOrderByOrderIds(List<Long> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return new ArrayList<>();
        }
        PtOrderQueryReq req = new PtOrderQueryReq();
        req.setOrderIdList(orderIds);
        req.setPage(1);
        req.setSize(Integer.MAX_VALUE);

        List<PtOrderEntity> list = ptOrderRepository.listOrder(req);
        return OrderConvert.batchToPtOrders(list);
    }


    public PtOrderDto queryPtOrderByOrderId(Long orderId) {
        PtOrderEntity entity = doQueryPtOrderByOrderId(orderId);
        if (entity == null) {
            return null;
        }
        return OrderConvert.toPtOrder(entity);
    }

    private PtOrderEntity doQueryPtOrderByOrderId(Long orderId) {
        return ptOrderRepository.queryPtOrderByOrderId(orderId);
    }


    /**
     * 根据拼团code进行查询
     *
     * @param ptOrder 拼团单code
     * @return
     */
    public List<PtOrderItemEntity> queryOrdersByPtOrderCode(String ptOrder) {
        return ptOrderRepository.listOrderByCode(ptOrder);
    }
}
